<template>
  <div class="mqtt-config">
    <el-card class="config-card">
      <template #header>
        <div class="card-header">
          <el-icon><Connection /></el-icon>
          <span>MQTT配置管理</span>
          <div class="header-actions">
            <el-button type="primary" @click="saveConfig" :loading="saving">
              <el-icon><Check /></el-icon>
              保存配置
            </el-button>
            <el-button @click="resetConfig">
              <el-icon><RefreshLeft /></el-icon>
              重置
            </el-button>
            <el-button @click="testConnection" :loading="testing">
              <el-icon><Link /></el-icon>
              测试连接
            </el-button>
          </div>
        </div>
      </template>

      <el-form
        ref="formRef"
        :model="mqttConfig"
        :rules="formRules"
        label-width="120px"
        size="default"
      >
        <el-form-item label="测试模式">
          <el-select v-model="testOptions.mode" style="width: 240px">
            <el-option label="连接+上报（默认）" value="connect_publish"/>
            <el-option label="仅连接" value="connect_only"/>
            <el-option label="全流程（登录+同步+上报）" value="full"/>
            <el-option label="注册+登录+上报（需平台支持）" value="register_login"/>
          </el-select>
        </el-form-item>
        <el-form-item label="实时模式">
          <el-switch v-model="testOptions.stream" active-text="SSE" inactive-text="HTTP" />
          <span class="form-tip">SSE可边执行边推送时间线与消息</span>
        </el-form-item>
        <!-- Broker连接配置 -->
        <el-divider content-position="left">
          <el-icon><Monitor /></el-icon>
          Broker连接配置
        </el-divider>
        
        <el-row :gutter="20">
          <el-col :xs="24" :md="12">
            <el-form-item label="服务器地址" prop="broker.host" required>
              <el-input 
                v-model="mqttConfig.broker.host" 
                placeholder="请输入MQTT Broker地址"
                clearable
              />
            </el-form-item>
          </el-col>
          
          <el-col :xs="24" :md="12">
            <el-form-item label="端口" prop="broker.port" required>
              <el-input-number
                v-model="mqttConfig.broker.port"
                :min="1"
                :max="65535"
                style="width: 100%"
                placeholder="端口号"
              />
            </el-form-item>
          </el-col>
        </el-row>

        <el-form-item label="启用TLS" prop="broker.use_tls">
          <el-switch 
            v-model="mqttConfig.broker.use_tls"
            active-text="启用"
            inactive-text="禁用"
          />
          <span class="form-tip">启用后使用加密连接，需要配置证书文件</span>
        </el-form-item>

        <!-- TLS证书配置 -->
        <template v-if="mqttConfig.broker.use_tls">
          <el-divider content-position="left">
            <el-icon><Lock /></el-icon>
            TLS证书配置
          </el-divider>
          
          <el-form-item label="CA证书文件" prop="broker.ca_file">
            <el-input 
              v-model="mqttConfig.broker.ca_file" 
              placeholder="/etc/ssl/certs/ca.crt"
              clearable
            />
          </el-form-item>
          
          <el-form-item label="客户端证书" prop="broker.cert_file">
            <el-input 
              v-model="mqttConfig.broker.cert_file" 
              placeholder="/etc/ssl/certs/client.crt"
              clearable
            />
          </el-form-item>
          
          <el-form-item label="私钥文件" prop="broker.key_file">
            <el-input 
              v-model="mqttConfig.broker.key_file" 
              placeholder="/etc/ssl/private/client.key"
              type="password"
              show-password
              clearable
            />
          </el-form-item>
        </template>

        <!-- 客户端配置 -->
      <el-divider content-position="left">
          <el-icon><User /></el-icon>
          客户端配置
      </el-divider>

      <el-row :gutter="20">
        <el-col :xs="24" :md="12">
          <el-form-item label="客户端ID" prop="client.client_id">
            <el-input 
              v-model="mqttConfig.client.client_id" 
              placeholder="例如 ems-client"
              clearable
            />
          </el-form-item>
        </el-col>

        <el-col :xs="24" :md="12">
          <el-form-item label="设备序列号" prop="client.device_sn" required>
            <el-input 
              v-model="mqttConfig.client.device_sn" 
              placeholder="设备唯一标识"
              clearable
            />
          </el-form-item>
        </el-col>
          
          <el-col :xs="24" :md="12">
            <el-form-item label="设备类型" prop="client.device_type" required>
              <el-input 
                v-model="mqttConfig.client.device_type" 
                placeholder="设备类型编号"
                clearable
              />
            </el-form-item>
          </el-col>
      </el-row>

      <el-row :gutter="20">
        <el-col :xs="24" :md="12">
          <el-form-item label="用户名" prop="client.username">
            <el-input 
              v-model="mqttConfig.client.username" 
              placeholder="MQTT用户名"
              clearable
            />
          </el-form-item>
        </el-col>

        <el-col :xs="24" :md="12">
          <el-form-item label="密码" prop="client.password">
            <el-input 
              v-model="mqttConfig.client.password" 
              placeholder="MQTT密码"
              type="password"
              show-password
              clearable
            />
          </el-form-item>
        </el-col>
      </el-row>

      <el-row :gutter="20">
        <el-col :xs="24" :md="12">
          <el-form-item label="保活时间(秒)" prop="client.keep_alive" required>
            <el-input-number
              v-model="mqttConfig.client.keep_alive"
              :min="30"
              :max="1200"
              style="width: 100%"
              placeholder="保活时间"
            />
            <span class="form-tip">建议300秒以上</span>
          </el-form-item>
        </el-col>
          
          <el-col :xs="24" :md="12">
            <el-form-item label="消息质量" prop="client.qos" required>
              <el-select v-model="mqttConfig.client.qos" style="width: 100%">
                <el-option label="QoS 0 - 最多一次" :value="0" />
                <el-option label="QoS 1 - 至少一次" :value="1" />
                <el-option label="QoS 2 - 恰好一次" :value="2" />
              </el-select>
            </el-form-item>
          </el-col>
      </el-row>

      <el-form-item label="清除会话" prop="client.clean_session">
        <el-switch 
          v-model="mqttConfig.client.clean_session"
          active-text="启用"
          inactive-text="禁用"
        />
        <span class="form-tip">启用后每次连接都会创建新会话</span>
      </el-form-item>

      <el-form-item label="保留消息" prop="client.retained">
        <el-switch 
          v-model="mqttConfig.client.retained"
          active-text="是"
          inactive-text="否"
        />
        <span class="form-tip">发布消息时是否设置 retain 标记</span>
      </el-form-item>

        <!-- Topic配置 -->
      <el-divider content-position="left">
          <el-icon><ChatDotSquare /></el-icon>
          Topic配置
      </el-divider>

      <el-row :gutter="20">
        <el-col :xs="24" :md="12">
          <el-form-item label="Topic前缀" prop="topics.topic_prefix">
            <el-input 
              v-model="mqttConfig.topics.topic_prefix" 
              placeholder="/ext/${deviceSn}/register"
              clearable
            />
          </el-form-item>
        </el-col>

        <el-col :xs="24" :md="12">
          <el-form-item label="数据上报Topic" prop="topics.data_upload" required>
            <el-input 
              v-model="mqttConfig.topics.data_upload" 
              placeholder="up/gateway/report/data"
              clearable
            />
          </el-form-item>
        </el-col>
          
          <el-col :xs="24" :md="12">
            <el-form-item label="告警上报Topic" prop="topics.alarm_upload" required>
              <el-input 
                v-model="mqttConfig.topics.alarm_upload" 
                placeholder="up/gateway/report/alarm"
                clearable
              />
            </el-form-item>
          </el-col>
      </el-row>

      <!-- 安全与签名参数 -->
      <el-divider content-position="left">
        <el-icon><Lock /></el-icon>
        安全/签名
      </el-divider>
      <el-row :gutter="20">
        <el-col :xs="24" :md="12">
          <el-form-item label="签名算法" prop="security.sign_method">
            <el-input 
              v-model="mqttConfig.security.sign_method" 
              placeholder="hmacsha256"
              clearable
            />
          </el-form-item>
        </el-col>
        <el-col :xs="24" :md="12">
          <el-form-item label="设备类型密钥" prop="security.device_type_secret">
            <el-input 
              v-model="mqttConfig.security.device_type_secret" 
              placeholder="shkg_prod_plc_32764"
              clearable
            />
          </el-form-item>
        </el-col>
      </el-row>

        <el-row :gutter="20">
          <el-col :xs="24" :md="12">
            <el-form-item label="登录Topic" prop="topics.login" required>
              <el-input 
                v-model="mqttConfig.topics.login" 
                placeholder="up/gateway/login"
                clearable
              />
            </el-form-item>
          </el-col>
          
          <el-col :xs="24" :md="12">
            <el-form-item label="命令响应Topic" prop="topics.command_response" required>
              <el-input 
                v-model="mqttConfig.topics.command_response" 
                placeholder="up/gateway/func/res"
                clearable
              />
            </el-form-item>
          </el-col>
        </el-row>

        <el-row :gutter="20">
          <el-col :xs="24" :md="12">
            <el-form-item label="告警清除Topic" prop="topics.alarm_clear" required>
              <el-input 
                v-model="mqttConfig.topics.alarm_clear" 
                placeholder="up/gateway/report/alarm_clear"
                clearable
              />
            </el-form-item>
          </el-col>

          <el-col :xs="24" :md="12">
            <el-form-item label="设备同步响应Topic" prop="topics.device_sync" required>
              <el-input 
                v-model="mqttConfig.topics.device_sync" 
                placeholder="up/gateway/sync/res"
                clearable
              />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
    </el-card>

    <!-- 连接测试结果 -->
    <el-card v-if="testResult" class="test-result-card">
      <template #header>
        <div class="card-header">
          <el-icon><DataAnalysis /></el-icon>
          <span>连接测试结果</span>
        </div>
      </template>
      
      <el-result
        :icon="testResult.success ? 'success' : 'error'"
        :title="testResult.success ? '连接成功' : '连接失败'"
        :sub-title="testResult.message"
      >
        <template #extra v-if="testResult.details">
          <el-descriptions border size="small">
            <el-descriptions-item label="响应时间" v-if="testResult.details.responseTime">
              {{ testResult.details.responseTime }}ms
            </el-descriptions-item>
            <el-descriptions-item label="连接协议" v-if="testResult.details.protocol">
              {{ testResult.details.protocol }}
            </el-descriptions-item>
            <el-descriptions-item label="测试时间">
              {{ new Date(testResult.timestamp).toLocaleString() }}
            </el-descriptions-item>
          </el-descriptions>
        </template>
      </el-result>

      <el-divider content-position="left">测试时间线</el-divider>
      <el-timeline v-if="displayTimeline.length">
        <el-timeline-item
          v-for="(s, idx) in displayTimeline"
          :key="idx"
          :type="timelineType(s.statusZh || s.status)"
          :color="timelineColor(s.statusZh || s.status)"
          :timestamp="(s.duration ?? 0) + ' ms'"
        >
          <div style="display:flex;align-items:center;gap:6px;">
            <el-icon v-if="(s.statusZh||s.status)==='成功'" color="#52c41a"><Check/></el-icon>
            <el-icon v-else-if="(s.statusZh||s.status)==='失败'" color="#ff4d4f"><Close/></el-icon>
            <strong>{{ s.nameZh || s.name }}</strong>
          </div>
          <div class="text-secondary">{{ s.detail }}</div>
        </el-timeline-item>
      </el-timeline>
    </el-card>

    <!-- 专用：MQTT消息控制台（实时显示收发） -->
    <el-card class="msg-console" shadow="never">
      <template #header>
        <div class="card-header">
          <el-icon><ChatDotSquare /></el-icon>
          <span>MQTT消息控制台</span>
          <div class="header-actions">
            <el-checkbox v-model="consoleFilter.send">仅发送</el-checkbox>
            <el-checkbox v-model="consoleFilter.recv">仅接收</el-checkbox>
            <el-switch v-model="consoleFilter.pretty" active-text="美化JSON" inactive-text="原文" />
            <el-switch v-model="consoleFilter.autoscroll" active-text="自动滚动" />
            <el-input v-model="consoleFilter.keyword" placeholder="搜索 Topic/内容" size="small" style="width:220px" clearable />
            <el-button size="small" @click="clearMessages">清空</el-button>
          </div>
        </div>
      </template>
      <div ref="consoleBodyRef" class="console-body">
        <div v-if="filteredMessages.length === 0" class="console-empty">暂无消息，开始测试或等待接收…</div>
        <div v-for="(m,i) in filteredMessages" :key="i" class="msg-item">
          <div class="msg-meta">
            <el-tag size="small" :type="m.dir==='send' ? 'success' : 'info'">{{ m.dir==='send' ? '发送' : '接收' }}</el-tag>
            <span class="msg-time">{{ m.time }}</span>
            <span class="msg-topic">Topic: {{ m.topic }}</span>
          </div>
          <pre class="msg-payload">{{ displayPayload(m.payload) }}</pre>
        </div>
      </div>
    </el-card>
  </div>
</template>

<script setup>
import { ref, reactive, onMounted, computed, watch, nextTick } from 'vue'
import { 
  Connection, Check, Close, RefreshLeft, Link, Monitor, Lock, User, 
  ChatDotSquare, DataAnalysis 
} from '@element-plus/icons-vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { configAPI, mqttAPI } from '@/utils/api'

// 表单引用
const formRef = ref()

// 响应式数据
const saving = ref(false)
const testing = ref(false)
const testResult = ref(null)
const testTimeline = ref([])
const testMessages = ref([])
const testOptions = reactive({
  mode: 'register_login', // 默认完整流程
  stream: true            // 默认启用SSE
})

// MQTT配置数据
const mqttConfig = reactive({
  broker: {
    host: '',
    port: 8883,
    use_tls: true,
    ca_file: '',
    cert_file: '',
    key_file: ''
  },
  client: {
    client_id: '',
    device_sn: '',
    device_type: '',
    username: '',
    password: '',
    keep_alive: 300,
    clean_session: true,
    qos: 1,
    retained: false
  },
  topics: {
    topic_prefix: '',
    data_upload: 'up/gateway/report/data',
    alarm_upload: 'up/gateway/report/alarm',
    alarm_clear: 'up/gateway/report/alarm_clear',
    device_sync: 'up/gateway/sync/res',
    login: 'up/gateway/login',
    command_response: 'up/gateway/func/res'
  },
  security: {
    sign_method: '',
    device_type_secret: ''
  }
})

// 原始配置备份
let originalConfig = {}

// 表单验证规则
const formRules = {
  'broker.host': [
    { required: true, message: '请输入MQTT Broker地址', trigger: 'blur' }
  ],
  'broker.port': [
    { required: true, message: '请输入端口号', trigger: 'blur' },
    { type: 'number', min: 1, max: 65535, message: '端口号范围1-65535', trigger: 'blur' }
  ],
  'client.device_sn': [
    { required: true, message: '请输入设备序列号', trigger: 'blur' }
  ],
  'client.device_type': [
    { required: true, message: '请输入设备类型', trigger: 'blur' }
  ],
  'client.keep_alive': [
    { required: true, message: '请输入保活时间', trigger: 'blur' },
    { type: 'number', min: 30, max: 1200, message: '保活时间范围30-1200秒', trigger: 'blur' }
  ],
  'topics.data_upload': [
    { required: true, message: '请输入数据上报Topic', trigger: 'blur' }
  ],
  'topics.alarm_upload': [
    { required: true, message: '请输入告警上报Topic', trigger: 'blur' }
  ],
  'topics.alarm_clear': [
    { required: true, message: '请输入告警清除Topic', trigger: 'blur' }
  ],
  'topics.device_sync': [
    { required: true, message: '请输入设备同步响应Topic', trigger: 'blur' }
  ],
  'topics.login': [
    { required: true, message: '请输入登录Topic', trigger: 'blur' }
  ],
  'topics.command_response': [
    { required: true, message: '请输入命令响应Topic', trigger: 'blur' }
  ]
}

// 方法
const loadConfig = async () => {
  try {
    const config = await configAPI.getMqttConfig()
    Object.assign(mqttConfig, config)
    originalConfig = JSON.parse(JSON.stringify(config))
  } catch (error) {
    ElMessage.error('加载MQTT配置失败: ' + error.message)
  }
}

const saveConfig = async () => {
  if (!formRef.value) return

  try {
    const valid = await formRef.value.validate()
    if (!valid) return

    saving.value = true
    
    await configAPI.updateMqttConfig(mqttConfig)
    originalConfig = JSON.parse(JSON.stringify(mqttConfig))
    
    ElMessage.success('MQTT配置保存成功')
  } catch (error) {
    ElMessage.error('保存MQTT配置失败: ' + error.message)
  } finally {
    saving.value = false
  }
}

const resetConfig = () => {
  ElMessageBox.confirm(
    '确定要重置MQTT配置吗？所有未保存的修改将丢失。',
    '重置确认',
    {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    }
  ).then(() => {
    Object.assign(mqttConfig, JSON.parse(JSON.stringify(originalConfig)))
    formRef.value?.clearValidate()
    testResult.value = null
    ElMessage.success('配置已重置')
  }).catch(() => {
    // 用户取消
  })
}

const testConnection = async () => {
  if (!formRef.value) return

  try {
    const valid = await formRef.value.validate()
    if (!valid) {
      ElMessage.warning('请先完善配置信息')
      return
    }

    // 实时(SSE)模式
    if (testOptions.stream) {
      testing.value = true
      testResult.value = null
      seedDocSteps()
      await startSseTest()
      return
    }
    testing.value = true
    testResult.value = null
    // 预置文档步骤，先全部展示
    seedDocSteps()
    // HTTP一次性返回
    const payload = JSON.parse(JSON.stringify(mqttConfig))
    payload.test_mode = testOptions.mode
    const result = await mqttAPI.testConnection(payload)

    testResult.value = {
      success: !!result.success,
      message: result.message || (result.success ? 'MQTT服务器连接正常' : 'MQTT连接失败'),
      details: result.details || null,
      timeline: result.timeline || [],
      timestamp: Date.now()
    }

    // 将返回的时间线按耗时“回放”，实现同步展示效果
    playTimeline(testResult.value.timeline)

    if (result.success) {
      ElMessage.success('MQTT连接测试成功')
    } else {
      ElMessage.error('MQTT连接测试失败')
    }
    // 回放消息
    if (Array.isArray(result.messages)) {
      playMessages(result.messages)
    }
  } catch (error) {
    testResult.value = {
      success: false,
      message: 'MQTT连接失败: ' + error.message,
      timestamp: Date.now()
    }
    ElMessage.error('MQTT连接测试失败')
  } finally {
    testing.value = false
  }
}

// 生命周期
onMounted(() => {
  loadConfig()
})

// 时间线样式辅助
const timelineType = (status) => {
  switch (status) {
    case 'ok':
    case '成功': return 'success'
    case 'fail':
    case '失败': return 'danger'
    case 'skip':
    case '跳过': return 'info'
    case '进行中': return 'warning'
    default: return ''
  }
}
const timelineColor = (status) => {
  switch (status) {
    case 'ok':
    case '成功': return '#52c41a'
    case 'fail':
    case '失败': return '#ff4d4f'
    case 'skip':
    case '跳过': return '#909399'
    case '进行中': return '#faad14'
    default: return ''
  }
}

// 时间线“实时展示”回放
const pushLocalStep = (s) => {
  testTimeline.value.push(s)
}
const seedDocSteps = () => {
  testTimeline.value = []
  const stepsMap = {
    connect_publish: ['初始化','连接','发布数据','断开连接'],
    connect_only: ['初始化','连接','断开连接'],
    full: ['初始化','连接','发布登录','订阅同步下行','发布同步响应','发布数据','断开连接'],
    register_login: ['初始化','动态注册','登录','发布登录','订阅同步下行','发布同步响应','发布数据','断开连接']
  }
  const steps = stepsMap[testOptions.mode] || stepsMap.connect_publish
  steps.forEach((name, idx) => {
    pushLocalStep({ nameZh: name, statusZh: idx===0 ? '进行中' : '待执行', detail: '', duration: 0 })
  })
}
const updateLocalStep = (name, status, detail, duration) => {
  const i = testTimeline.value.findIndex(s => s.nameZh === name)
  if (i >= 0) {
    testTimeline.value[i] = {
      ...testTimeline.value[i],
      statusZh: status || testTimeline.value[i].statusZh,
      detail: detail ?? testTimeline.value[i].detail,
      duration: duration ?? testTimeline.value[i].duration
    }
    // 设置下一个待执行为进行中
    if (status === '成功' || status === '失败' || status === '跳过') {
      const next = testTimeline.value.findIndex((s, idx) => idx > i && s.statusZh === '待执行')
      if (next >= 0) testTimeline.value[next].statusZh = '进行中'
    }
  } else {
    pushLocalStep({ nameZh: name, statusZh: status, detail, duration })
  }
}
const translateStep = (s) => {
  const m = { ok: '成功', fail: '失败', skip: '跳过' }
  return {
    nameZh: s.name, // 后端已中文
    detail: s.detail,
    duration: s.duration,
    statusZh: m[s.status] || s.status
  }
}
const playTimeline = (list) => {
  if (!Array.isArray(list)) return
  let delay = 0
  const scale = 0.3 // 加速系数
  list.forEach((s) => {
    const d = Math.max(80, Math.round((s.duration || 0) * scale))
    setTimeout(() => {
      const t = translateStep(s)
      updateLocalStep(t.nameZh, t.statusZh, t.detail, t.duration)
    }, delay)
    delay += d
  })
}

// 消息回放/追加
const pushMessage = (m) => { testMessages.value.push(m) }
const playMessages = (list) => {
  let delay = 0
  const step = 80
  list.forEach((m) => { setTimeout(() => pushMessage(m), delay); delay += step })
}

// SSE 实时
let es = null
const startSseTest = async () => {
  if (es) { es.close(); es = null }
  testMessages.value = []
  const url = `/api/mqtt/test/stream?test_mode=${encodeURIComponent(testOptions.mode)}`
  es = new EventSource(url)
  es.addEventListener('start', () => {})
  es.addEventListener('step', (e) => {
    try {
      const s = JSON.parse(e.data)
      const statusZh = ({ ok: '成功', fail: '失败', skip: '跳过' }[s.status]) || s.status || '成功'
      updateLocalStep(s.name || s.nameZh, statusZh, s.detail, s.duration)
    } catch {}
  })
  es.addEventListener('message', (e) => { try { pushMessage(JSON.parse(e.data)) } catch {} })
  es.addEventListener('end', (e) => {
    try {
      const res = JSON.parse(e.data)
      testResult.value = { success: !!res.success, message: res.message || (res.success? '连接成功':'连接失败'), details: res.details || null, timestamp: Date.now() }
      ElMessage[res.success? 'success':'error'](testResult.value.message)
    } catch {}
    testing.value = false
    es && es.close(); es = null
  })
  es.addEventListener('error', () => {
    testing.value = false
    ElMessage.error('SSE连接中断')
    es && es.close(); es = null
  })
}

// 展示用数据源（优先用同步时间线）
const displayTimeline = computed(() => {
  return testTimeline.value.length ? testTimeline.value : (testResult.value?.timeline || [])
})

// 控制台筛选/展示
const consoleFilter = reactive({ send: false, recv: false, keyword: '', pretty: true, autoscroll: true })
const consoleBodyRef = ref(null)
const filteredMessages = computed(() => {
  return testMessages.value.filter(m => {
    if (consoleFilter.send && m.dir !== 'send') return false
    if (consoleFilter.recv && m.dir !== 'recv') return false
    if (consoleFilter.keyword) {
      const k = consoleFilter.keyword.toLowerCase()
      if (!(`${m.topic}`.toLowerCase().includes(k) || `${m.payload}`.toLowerCase().includes(k))) return false
    }
    return true
  })
})
const clearMessages = () => { testMessages.value = [] }
const displayPayload = (raw) => {
  if (!consoleFilter.pretty) return raw
  try {
    const obj = JSON.parse(raw)
    return JSON.stringify(obj, null, 2)
  } catch (_) {
    try {
      const unescaped = raw.replace(/\\\"/g, '"')
      const obj2 = JSON.parse(unescaped)
      return JSON.stringify(obj2, null, 2)
    } catch { return raw }
  }
}
watch(filteredMessages, async () => {
  if (!consoleFilter.autoscroll) return
  await nextTick()
  const el = consoleBodyRef.value
  if (el) el.scrollTop = el.scrollHeight
})
</script>

<style scoped>
.mqtt-config {
  max-width: 1000px;
  margin: 0 auto;
}

.config-card {
  margin-bottom: 20px;
}

.card-header {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 600;
}

.header-actions {
  margin-left: auto;
  display: flex;
  gap: 12px;
}

.form-tip {
  color: #8c8c8c;
  font-size: 12px;
  margin-left: 8px;
}

.test-result-card {
  margin-top: 20px;
}

.text-secondary {
  color: #8c8c8c;
  font-size: 12px;
}

.msg-console { margin-top: 20px; }
.console-body { max-height: 360px; overflow: auto; background: #fff; border: 1px solid #eee; border-radius: 6px; padding: 8px 12px; }
.console-empty { color: #909399; font-size: 13px; padding: 12px 0; }
.msg-item { padding: 8px 0; border-bottom: 1px dashed #eee; }
.msg-item:last-child { border-bottom: none; }
.msg-meta { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; }
.msg-time { color: #8c8c8c; font-size: 12px; }
.msg-topic { color: #606266; font-size: 12px; }
.msg-payload { white-space: pre-wrap; background: #fafafa; padding: 8px; border-radius: 4px; overflow: auto; }

:deep(.el-divider__text) {
  background-color: var(--el-bg-color);
  padding: 0 16px;
  font-weight: 500;
  color: var(--el-text-color-primary);
}

:deep(.el-form-item) {
  margin-bottom: 20px;
}

:deep(.el-input-number) {
  width: 100%;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .header-actions {
    flex-direction: column;
    gap: 8px;
  }
  
  .header-actions .el-button {
    width: 100%;
  }
}
</style>
